﻿using System.Collections.Generic;

namespace DynamicGeometry
{
    public class Transformer
    {
        
        public static List<IFigure> CreateReflectedFigure(Drawing drawing, IFigure source, IFigure mirror)
        {
            Check.NotNull(source, "source");
            Check.NotNull(mirror, "mirror");

            List<IFigure> result = new List<IFigure>();
            if (source is IPoint)
            {
                var reflectedPoint = Factory.CreateReflectedPoint(drawing, new FigureList() { source, mirror });
                if (reflectedPoint == null)
                {
                    throw "reflectedPoint is null. source = {0}, mirror = {1}"
                        .Format(source, mirror)
                        .AsException();
                }
                result.Add(reflectedPoint);
            }
            else if (source is ILine || source is ICircle || source is PolygonBase)
            {
                var dependencies = new FigureList();
                foreach (var dependency in source.Dependencies)
                {
                    var reflectedDependency = CreateReflectedFigure(drawing, dependency, mirror);
                    if (reflectedDependency == null)
                    {
                        throw "reflectedDependency is null. dependency = {0}, mirror = {1}"
                            .Format(dependency, mirror)
                            .AsException();
                    }
                    if (reflectedDependency.IsEmpty())
                    {
                        throw "reflectedDependency is empty. dependency = {0}, mirror = {1}"
                            .Format(dependency, mirror)
                            .AsException();
                    }
                    result.AddRange(reflectedDependency);
                    var last = reflectedDependency.Last();
                    if (last == null)
                    {
                        throw "last = null".AsException();
                    }
                    dependencies.Add(last);
                }
                var reflected = source.Clone();
                if (reflected == null)
                {
                    throw "reflected = null".AsException();
                }
                reflected.Dependencies = dependencies;
                result.Add(reflected);
            }
            return result;
        }

        public static List<IFigure> CreateDilatedFigure(Drawing drawing, IFigure source, IFigure center, double factor)
        {
            Check.NotNull(source, "source");
            Check.NotNull(center, "center");

            List<IFigure> result = new List<IFigure>();
            if (source is IPoint)
            {
                var dilatedPoint = Factory.CreateDilatedPoint(drawing, new FigureList() { source, center }, factor);
                if (dilatedPoint == null)
                {
                    throw "dilatedPoint is null. source = {0}, center = {1}, factor = {2}"
                        .Format(source, center, factor)
                        .AsException();
                }
                result.Add(dilatedPoint);
            }
            else if (source is ILine || source is ICircle || source is PolygonBase)
            {
                var dependencies = new FigureList();
                foreach (var dependency in source.Dependencies)
                {
                    var dilatedDependency = CreateDilatedFigure(drawing, dependency, center, factor);
                    if (dilatedDependency == null)
                    {
                        throw "dilatedDependency is null. dependency = {0}, center = {1}, factor = {2}"
                            .Format(dependency, center, factor)
                            .AsException();
                    }
                    if (dilatedDependency.IsEmpty())
                    {
                        throw "dilatedDependency is empty. dependency = {0}, center = {1}, factor = {2}"
                            .Format(dependency, center, factor)
                            .AsException();
                    }
                    result.AddRange(dilatedDependency);
                    var last = dilatedDependency.Last();
                    if (last == null)
                    {
                        throw "last = null".AsException();
                    }
                    dependencies.Add(last);
                }
                var dilated = source.Clone();
                if (dilated == null)
                {
                    throw "dilated = null".AsException();
                }
                dilated.Dependencies = dependencies;
                result.Add(dilated);
            }
            return result;
        }

        public static List<IFigure> CreateRotatedFigure(Drawing drawing, IFigure source, IFigure center, double angle)
        {
            Check.NotNull(source, "source");
            Check.NotNull(center, "center");

            List<IFigure> result = new List<IFigure>();
            if (source is IPoint)
            {
                var rotatedPoint = Factory.CreateRotatedPoint(drawing, new FigureList() { source, center }, angle);
                if (rotatedPoint == null)
                {
                    throw "rotatedPoint is null. source = {0}, center = {1}, angle = {2}"
                        .Format(source, center, angle)
                        .AsException();
                }
                result.Add(rotatedPoint);
            }
            else if (source is ILine || source is ICircle || source is PolygonBase)
            {
                var dependencies = new FigureList();
                foreach (var dependency in source.Dependencies)
                {
                    var rotatedDependency = CreateRotatedFigure(drawing, dependency, center, angle);
                    if (rotatedDependency == null)
                    {
                        throw "rotatedDependency is null. dependency = {0}, center = {1}, angle = {2}"
                            .Format(dependency, center, angle)
                            .AsException();
                    }
                    if (rotatedDependency.IsEmpty())
                    {
                        throw "rotatedDependency is empty. dependency = {0}, center = {1}, angle = {2}"
                            .Format(dependency, center, angle)
                            .AsException();
                    }
                    result.AddRange(rotatedDependency);
                    var last = rotatedDependency.Last();
                    if (last == null)
                    {
                        throw "last = null".AsException();
                    }
                    dependencies.Add(last);
                }
                var rotated = source.Clone();
                if (rotated == null)
                {
                    throw "rotated = null".AsException();
                }
                rotated.Dependencies = dependencies;
                result.Add(rotated);
            }
            return result;
        }

        public static List<IFigure> CreateTranslatedFigure(Drawing drawing, IFigure source, double magnitude, double direction)
        {
            Check.NotNull(source, "source");

            List<IFigure> result = new List<IFigure>();
            if (source is IPoint)
            {
                var translatedPoint = Factory.CreateTranslatedPoint(drawing, new FigureList() { source }, magnitude, direction);
                if (translatedPoint == null)
                {
                    throw "translatedPoint is null. source = {0}, magnitude = {1}, direction = {2}"
                        .Format(source, magnitude, direction)
                        .AsException();
                }
                result.Add(translatedPoint);
            }
            else if (source is ILine || source is ICircle || source is PolygonBase)
            {
                var dependencies = new FigureList();
                foreach (var dependency in source.Dependencies)
                {
                    var translatedDependency = CreateTranslatedFigure(drawing, dependency, magnitude, direction);
                    if (translatedDependency == null)
                    {
                        throw "translatedDependency is null. dependency = {0}, center = {1}, direction = {2}"
                            .Format(dependency, magnitude, direction)
                            .AsException();
                    }
                    if (translatedDependency.IsEmpty())
                    {
                        throw "translatedDependency is empty. dependency = {0}, center = {1}, direction = {2}"
                            .Format(dependency, magnitude, direction)
                            .AsException();
                    }
                    result.AddRange(translatedDependency);
                    var last = translatedDependency.Last();
                    if (last == null)
                    {
                        throw "last = null".AsException();
                    }
                    dependencies.Add(last);
                }
                var translated = source.Clone();
                if (translated == null)
                {
                    throw "translated = null".AsException();
                }
                translated.Dependencies = dependencies;
                result.Add(translated);
            }
            return result;
        }

    }
}